﻿using NLog;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using IOA.MES.Business;
using IOA.MES.DataAccess.Enum;
using Newtonsoft.Json;
using IOA.MES.Common;

namespace IOA.MES.ClientApi
{
    public class CommonFilter : ActionFilterAttribute, IActionFilter
    {
        private Logger logger = LogManager.GetLogger(nameof(CommonFilter));
        private Stopwatch watcher;
        private object lockObj = new object();
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            watcher = new Stopwatch();
            watcher.Start();

            var anonymousApis = System.Configuration.ConfigurationManager.AppSettings["AnonymousApis"].ToString()
                .Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(_ => _.ToLower().Trim()).ToList();
            if (anonymousApis.Contains(actionContext.Request.RequestUri.AbsolutePath.ToLower().Trim()))
            {
                base.OnActionExecuting(actionContext);
                return;
            }

            var userToken = new UserMgr().GetToken(BaseEnv.Token);

            if (userToken == null)
            {
                actionContext.Response = new HttpResponseMessage
                {
                    StatusCode = System.Net.HttpStatusCode.OK,
                    Content = new StringContent(JsonConvert.SerializeObject(new ResultJson<object>(401, "尚未登录")), Encoding.UTF8, "application/json")
                };
            }
            else if (userToken.Expires < DateTime.Now)
            {
                actionContext.Response = new HttpResponseMessage
                {
                    StatusCode = System.Net.HttpStatusCode.OK,
                    Content = new StringContent(JsonConvert.SerializeObject(new ResultJson<object>(401, "登录已过期，请重新登陆")), Encoding.UTF8, "application/json")
                };
            }
            else
            {
                var user = new UserMgr().GetUser(userToken.UserId);
                if (user == null)
                {
                    actionContext.Response = new HttpResponseMessage
                    {
                        StatusCode = System.Net.HttpStatusCode.OK,
                        Content = new StringContent(JsonConvert.SerializeObject(new ResultJson<object>(401, "数据错误，用户信息不存在")), Encoding.UTF8, "application/json")
                    };
                }
                else if (user.Status != CommonStatus.Normal)
                {
                    actionContext.Response = new HttpResponseMessage
                    {
                        StatusCode = System.Net.HttpStatusCode.OK,
                        Content = new StringContent(JsonConvert.SerializeObject(new ResultJson<object>(401, "用户账户异常，请联系客服")), Encoding.UTF8, "application/json")
                    };
                }
            }
            if (string.IsNullOrWhiteSpace(BaseEnv.WorkshopCode) && !actionContext.Request.RequestUri.AbsolutePath.StartsWith("/api/WebTool/", StringComparison.CurrentCultureIgnoreCase))
            {
                actionContext.Response = new HttpResponseMessage
                {
                    StatusCode = System.Net.HttpStatusCode.OK,
                    Content = new StringContent(JsonConvert.SerializeObject(new ResultJson<object>(401, "车间信息不存在")), Encoding.UTF8, "application/json")
                };
            }

            base.OnActionExecuting(actionContext);
        }

        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            watcher.Stop();
            try
            {
                var request = HttpContext.Current.Request;
                if (request.Url.AbsolutePath.ToString().ToLower().Contains("common/ping"))
                {
                    base.OnActionExecuted(actionExecutedContext);
                    return;
                }

                HttpContext.Current.Request.InputStream.Position = 0;
                var length = HttpContext.Current.Request.InputStream.Length;
                var buffer = new byte[length];
                HttpContext.Current.Request.InputStream.Read(buffer, 0, (int)length);

                var dictLog = new Dictionary<string, object>();
                dictLog.Add("Url", request.Url.AbsolutePath.ToString());
                dictLog.Add("Elapsed", watcher.ElapsedMilliseconds);
                dictLog.Add("Token", BaseEnv.Token);
                dictLog.Add("ClientVersion", BaseEnv.GetHeader("ClientVersion"));
                dictLog.Add("Body", request.Url.AbsolutePath.ToString().ToLower().Contains("common/upload") ? "文件对象" : Encoding.UTF8.GetString(buffer));

                if (actionExecutedContext.Exception == null)
                {
                    var response = string.Empty;
                    try
                    {
                        if (string.Equals(request.Url.AbsolutePath.ToString(), "/api/Machine/QueryViaSiteRecords", StringComparison.CurrentCultureIgnoreCase))
                        {
                            response = "查询过站记录不记录日志";
                        }
                        else
                        {
                            response = actionExecutedContext.Response.Content.ReadAsStringAsync().Result;
                        }
                    }
                    catch (Exception ex)
                    {
                        logger.Fatal(ex, $"OnActionExecuted读取Response出错：{ex.Message}");
                    }
                    dictLog.Add("Response", response);
                    logger.Info(JsonConvert.SerializeObject(dictLog));
                }
                else
                {
                    var errMsg = actionExecutedContext.Exception.Message;
                    var response = new ResultJson<object>(500, "ErrCode:500\r\n服务器忙\r\nServer Error\r\nLỗi máy chủ");
                    if (actionExecutedContext.Exception is MultiLanBizException)
                    {
                        var bizException = actionExecutedContext.Exception as MultiLanBizException;
                        dictLog.Add("ErrCode", bizException.ErrCode);
                        errMsg = BaseEnv.GetErrMsg(bizException.ErrCode, bizException.ErrParas);
                        response = new ResultJson<object>(bizException.ErrCode, $"ErrCode:{bizException.ErrCode}\r\n{errMsg}");
                    }

                    dictLog.Add("Response", response);
                    actionExecutedContext.Response = new HttpResponseMessage
                    {
                        StatusCode = System.Net.HttpStatusCode.OK,
                        Content = new StringContent(JsonConvert.SerializeObject(response), Encoding.UTF8, "application/json")
                    };

                    if (response.ErrCode == 500)
                    {
                        logger.Fatal(actionExecutedContext.Exception, JsonConvert.SerializeObject(dictLog));
                    }
                    else
                    {
                        logger.Warn(JsonConvert.SerializeObject(dictLog));
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Fatal(ex, $"OnActionExecuted出错：{ex.Message}");
            }

            base.OnActionExecuted(actionExecutedContext);
        }
    }
}
